/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/** ************************************************************************************************
 * @file     sdrv_fmmu_lld.c                                                                       *
 * @brief    LLD fmmu Driver                                                                       *
 * @author   Department/Semidrive                                                                  *
 * @date     2024/11/21                                                                            *
 *                                                                                                 *
 **************************************************************************************************/

#include "lld_platform.h"
#ifdef CFG_PLATFORM_MCAL
#include "RegHelper.h"
#else
#include "reg.h"
#endif
#include "sdrv_fmmu_lld.h"
#include "fmmu_ip.h"

/***************************************************************************************************
 *                                 Private Macro definition                                        *
 **************************************************************************************************/
/**
 * fmmu register
 */
#define FMMU_REMAP_CTL(regionId)                (0x0u    + 12u * (regionId))
#define FMMU_REMAP_SRC_ADDR(regionId)           (0x4u    + 12u * (regionId))
#define FMMU_REMAP_DST_ADDR(regionId)           (0x8u    + 12u * (regionId))
#define FMMU_REMAP_CTL_MON(regionId)            (0x600ul + 12u * (regionId))
#define FMMU_REMAP_SRC_ADDR_MON(regionId)       (0x604ul + 12u * (regionId))
#define FMMU_REMAP_DST_ADDR_MON(regionId)       (0x608ul + 12u * (regionId))
#define FMMU_REMAP_EN(regionId)                 (0xC00ul + 4u  * ((regionId) / FMMU_EN_NUM))
#define FMMU_REMAP_EN_STATUS(regionId)          (0xC20ul + 4u  * ((regionId) / FMMU_EN_NUM))
#define FMMU_REMAP_EN_LATCH(regionId)           (0xC40ul + 4u  * ((regionId) / FMMU_EN_NUM))
#define FMMU_FUSA_UNC_ERR_IRQ_STAT              (0xD00U)
#define FMMU_FUSA_UNC_ERR_IRQ_UDP_EN            (0xD04U)
#define FMMU_FUSA_UNC_ERR_IRQ_SIG_EN            (0xD08U)
#define FMMU_FUSA_COR_ERR_IRQ_STAT              (0xD0CU)
#define FMMU_FUSA_COR_ERR_IRQ_UPD_EN            (0xD10U)
#define FMMU_FUSA_COR_ERR_IRQ_SIG_EN            (0xD14U)
#define FMMU_REG_PARITY_ERR_INT_STAT            (0xD20U)
#define FMMU_REG_PARITY_ERR_INT_SIG_EN          (0xD24U)
#define FMMU_PWDATA_INJ                         (0xD30U)
#define FMMU_PWECC_INJ                          (0xD34U)
#define FMMU_PRDATAINJ                          (0xD38U)
#define FMMU_MON_ERR_INJ_EN                     (0xD40U)
#define FMMU_SYS_REMAP_INJ                      (0xD44U)
#define FMMU_SOC_REMAP_INJ                      (0xD48U)
#define FMMU_REVISION                           (0xFFF0U)
#define FMMU_CFG_PARA                           (0xFFF4U)


#define FMMU_REMAP_SIZE_MASK                    (0xFU)
#define FMMU_REMAP_SRC_ADDR_MASK                (0x3FFFFFFul)
#define FMMU_REMAP_DST_ADDR_MASK                (0x3FFFFFFul)
#define FMMU_REMAP_EN_MASK                      (0x1u)
#define FMMU_REMAP_EN_LSB                       (0u)
#define FMMU_REMAP_MON_EN_LSB                   (16u)
#define FMMU_REMAP_EN_OFF(regionId)             (FMMU_REMAP_EN_MASK << ((regionId) + FMMU_REMAP_EN_LSB))
#define FMMU_REMAP_MON_EN_OFF(regionId)         (FMMU_REMAP_EN_MASK << ((regionId) + FMMU_REMAP_MON_EN_LSB))

/***************************************************************************************************
 *                                    Private Type Declarations                                    *
 **************************************************************************************************/

/***************************************************************************************************
 *                                  Private Variable Definitions                                   *
 **************************************************************************************************/

/***************************************************************************************************
 *                                  Private Function Declarations                                  *
 **************************************************************************************************/
#ifdef CFG_PLATFORM_MCAL
#define FMMU_START_SEC_CODE
#include "Fmmu_MemMap.h"
#endif /* #ifdef CFG_PLATFORM_MCAL */
static lld_status_t Fmmu_Check_RegionId(Fmmu_Core_t core, Fmmu_Type_t remapType, uint8_t regionId)
{
    lld_status_t errorId = FMMU_E_PARAM_INVALID;
    uint8_t i;

    for (i = 0; i < FMMU_MAX_NUM; i++)
    {
        /* Check if the coreType and FmmuType correspond. */
        if (Fmmu_AttributeTable[i].core == core &&
            Fmmu_AttributeTable[i].fmmuType == remapType)
        {
            errorId = FMMU_NO_ERROR;

            if (regionId >= Fmmu_AttributeTable[i].regionNum)
            {
                errorId = FMMU_E_OVER_REGIONNUM;
                break;
            }/* else not needed */
        }/* else not needed */
    }

    return errorId;
}

static lld_status_t Fmmu_Check_RemapAddr(const Fmmu_RegionConfigType * config)
{
    lld_status_t errorId = FMMU_NO_ERROR;
    Fmmu_Type_t type = config->type;
    uint32_t srcStartAddr = config->srcAddr;
    uint32_t srcEndAddr = config->srcAddr + (FMMU_REMAP_SIZE(config->remapSize) - 1);
    uint32_t dstStartAddr = config->dstAddr;
    uint32_t dstEndAddr = config->dstAddr + (FMMU_REMAP_SIZE(config->remapSize) - 1);

    uint8_t i;
    uint8_t srcRangeOk = 0;
    uint8_t dstRangeOk = 0;

    if (config->remapSize >= FMMU_SIZE_MAX) /* Check RemapSize Effective */
    {
        errorId = FMMU_E_PARAM_INVALID;
    }
    else
    {
        for (i = 0; i < FMMU_SRC_RANGE_NUM; i++)
        {
            if (Fmmu_SrcAddrRangeTable[i].fmmuType == type)
            {
                if ((srcStartAddr >= Fmmu_SrcAddrRangeTable[i].startAddr) && (srcEndAddr <= Fmmu_SrcAddrRangeTable[i].endAddr))
                {
                    srcRangeOk = 1;
                }
            }
        }

        for (i = 0; i < FMMU_DST_RANGE_NUM; i++)
        {
            if (Fmmu_DstAddrRangeTable[i].fmmuType == type)
            {
                if ((dstStartAddr >= Fmmu_DstAddrRangeTable[i].startAddr) && (dstEndAddr <= Fmmu_DstAddrRangeTable[i].endAddr))
                {
                    dstRangeOk = 1;
                }
            }
        }

        if (0 == srcRangeOk)
        {
            errorId = FMMU_E_SRCADDR_INVALID;
        }
        else if (0 == dstRangeOk)
        {
            errorId = FMMU_E_DSTADDR_INVALID;
        }
        else /* check addr aligend size */
        {
            if ((srcStartAddr % FMMU_REMAP_SIZE(config->remapSize)) ||
                (dstStartAddr % FMMU_REMAP_SIZE(config->remapSize)) )
            {
                errorId = FMMU_E_NOT_ALIGNED_SIZE;
            } /* else not needed */
        }
    }

    return errorId;
}

static lld_status_t Fmmu_Init_Check_Config(Fmmu_Core_t core, const Fmmu_ConfigType * config, uint32_t regionNum)
{
    lld_status_t errorId = FMMU_NO_ERROR;
    uint32_t remapAddrMap[FMMU_REGION_NUM_MAX][2];
    uint32_t i, j;

    for (i = 0; i < regionNum; i++)
    {
        if (config[i].en > FMMU_REGION_EN)
        {
            errorId = FMMU_E_PARAM_INVALID;
            break;
        } /* else not needed */

        if (config[i].lock > FMMU_LOCK_EN)
        {
            errorId = FMMU_E_PARAM_INVALID;
            break;
        } /* else not needed */

        errorId = Fmmu_Check_RegionId(core, config[i].regionConfig.type, config[i].regionConfig.regionId);
        if (FMMU_NO_ERROR != errorId)
        {
            break;
        } /* else not needed */

        errorId = Fmmu_Check_RemapAddr(&config[i].regionConfig);
        if (FMMU_NO_ERROR != errorId)
        {
            break;
        } /* else not needed */

        /* bgenerate SrcAddrMap */
        remapAddrMap[i][0] = config[i].regionConfig.srcAddr;
        remapAddrMap[i][1] = config[i].regionConfig.srcAddr + FMMU_REMAP_SIZE(config[i].regionConfig.remapSize) - 1;
    }

    if (errorId == FMMU_NO_ERROR)
    {
        for (i = 0; i < (regionNum - 1); i++)     /* The last one doesn't need to be compared. */
        {
            for (j = (i + 1); j < regionNum; j++) /* Compared to the next one */
            {
                /* A EndAddr < B StartAddr || B EndAddr < A StartAddr  */
                if (!((remapAddrMap[i][1] < remapAddrMap[j][0]) || (remapAddrMap[j][1] < remapAddrMap[i][0])) )
                {
                    errorId = FMMU_E_SRCADDR_OVERLAP;
                    break;
                } /* else not needed */
            }

            if (errorId != FMMU_NO_ERROR)
            {
                break;
            } /* else not needed */
        }
    } /* else not needed */

    return errorId;
}

static uint32_t Fmmu_Get_Base(Fmmu_Core_t core, Fmmu_Type_t remapType)
{
    uint32_t base = 0;

    uint8_t i;

    for (i = 0; i < FMMU_MAX_NUM; i++)
    {
        /* Check if the coreType and FmmuType correspond. */
        if (Fmmu_AttributeTable[i].core == core &&
            Fmmu_AttributeTable[i].fmmuType == remapType)
        {
            base = Fmmu_AttributeTable[i].base;
        }
    }

    return base;
}

static uint32_t Fmmu_Get_Monitor(Fmmu_Core_t core, Fmmu_Type_t remapType)
{
    Fmmu_Monitor_t mon = FMMU_NO_MON;
    uint8_t i;

    for (i = 0; i < FMMU_MAX_NUM; i++)
    {
        /* Check if the coreType and FmmuType correspond. */
        if (Fmmu_AttributeTable[i].core == core &&
            Fmmu_AttributeTable[i].fmmuType == remapType)
        {
            mon = Fmmu_AttributeTable[i].monitor;
        }
    }

    return mon;
}

static uint32_t Fmmu_Get_RemapEnStatus(uint32_t base, uint8_t regionId)
{
    uint32_t value = readl(base + FMMU_REMAP_EN_STATUS(regionId));
    uint8_t bitNum = regionId % FMMU_EN_NUM;

    return (value >> bitNum) & FMMU_REMAP_EN_MASK;
}

static uint32_t Fmmu_Get_RemapLatchStatus(uint32_t base, uint8_t regionId)
{
    uint32_t value = readl(base + FMMU_REMAP_EN_LATCH(regionId));
    uint8_t bitNum = regionId % FMMU_EN_NUM;

    return (value >> bitNum) & FMMU_REMAP_EN_MASK;
}

static lld_status_t FMMU_Config_RemapParam(Fmmu_Core_t core, const Fmmu_RegionConfigType * config)
{
    lld_status_t errorId = FMMU_NO_ERROR;
    uint32_t base = Fmmu_Get_Base(core, config->type);

    uint32_t remapCtlvalue = config->remapSize;
    uint32_t remapSrcvalue = FMMU_ADDR_TO_OFF(config->srcAddr);
    uint32_t remapDstvalue = FMMU_ADDR_TO_OFF(config->dstAddr);

    if (Fmmu_Get_RemapEnStatus(base, config->regionId))
    {
        errorId = FMMU_E_REGION_ENABLED;
    }
    else if (Fmmu_Get_RemapLatchStatus(base, config->regionId))
    {
        errorId = FMMU_E_REGION_LOCKED;
    }

    if (errorId == FMMU_NO_ERROR)
    {
        writel(remapCtlvalue, base + FMMU_REMAP_CTL(config->regionId));
        writel(remapSrcvalue, base + FMMU_REMAP_SRC_ADDR(config->regionId));
        writel(remapDstvalue, base + FMMU_REMAP_DST_ADDR(config->regionId));

        if (remapCtlvalue != readl(base + FMMU_REMAP_CTL(config->regionId)))
        {
            errorId = FMMU_E_WRIT_REG_EXCEPTION;
        }
        else if (remapSrcvalue != readl(base + FMMU_REMAP_SRC_ADDR(config->regionId)))
        {
            errorId = FMMU_E_WRIT_REG_EXCEPTION;
        }
        else if (remapDstvalue != readl(base + FMMU_REMAP_DST_ADDR(config->regionId)))
        {
            errorId = FMMU_E_WRIT_REG_EXCEPTION;
        } /* else not needed */

        if (errorId == FMMU_NO_ERROR && Fmmu_Get_Monitor(core, config->type))
        {
            remapCtlvalue = ~remapCtlvalue & FMMU_REMAP_SIZE_MASK;
            writel(remapCtlvalue, base + FMMU_REMAP_CTL_MON(config->regionId));
            remapSrcvalue = ~remapSrcvalue & FMMU_REMAP_SRC_ADDR_MASK;
            writel(remapSrcvalue, base + FMMU_REMAP_SRC_ADDR_MON(config->regionId));
            remapDstvalue = ~remapDstvalue & FMMU_REMAP_DST_ADDR_MASK;
            writel(remapDstvalue, base + FMMU_REMAP_DST_ADDR_MON(config->regionId));

            if (remapCtlvalue != readl(base + FMMU_REMAP_CTL_MON(config->regionId)))
            {
                errorId = FMMU_E_WRIT_REG_EXCEPTION;
            }
            else if (remapSrcvalue != readl(base + FMMU_REMAP_SRC_ADDR_MON(config->regionId)))
            {
                errorId = FMMU_E_WRIT_REG_EXCEPTION;
            }
            else if (remapDstvalue != readl(base + FMMU_REMAP_DST_ADDR_MON(config->regionId)))
            {
                errorId = FMMU_E_WRIT_REG_EXCEPTION;
            } /* else not needed */
        }
    }

    return errorId;
}

static lld_status_t FMMU_Config_RemapEn(Fmmu_Core_t core, Fmmu_Type_t fmmuType, uint8_t regionId, Fmmu_RegionEn_t enable)
{
    lld_status_t errorId = FMMU_NO_ERROR;
    uint32_t base = Fmmu_Get_Base(core, fmmuType);
    uint32_t remapEnValue = readl(base + FMMU_REMAP_EN(regionId));

    if (Fmmu_Get_Monitor(core, fmmuType))
    {
        if (enable != 0)
        {   //enable
            remapEnValue |= FMMU_REMAP_EN_OFF(regionId % FMMU_EN_NUM);
            remapEnValue &= ~(FMMU_REMAP_MON_EN_OFF(regionId % FMMU_EN_NUM));
        }
        else
        {   //disable
            remapEnValue &= ~(FMMU_REMAP_EN_OFF(regionId % FMMU_EN_NUM));
            remapEnValue |= FMMU_REMAP_MON_EN_OFF(regionId % FMMU_EN_NUM);
        }
    }else
    {
        if (enable != 0)
        {   //enable
            remapEnValue |= FMMU_REMAP_EN_OFF(regionId % FMMU_EN_NUM);
        }
        else
        {   //disable
            remapEnValue &= ~(FMMU_REMAP_EN_OFF(regionId % FMMU_EN_NUM));
        }
    }

    writel(remapEnValue, base + FMMU_REMAP_EN(regionId));
    if (remapEnValue != readl(base + FMMU_REMAP_EN(regionId))) {
        errorId = FMMU_E_WRIT_REG_EXCEPTION;
    }/* else not needed */

    return errorId;
}

static lld_status_t FMMU_Config_RemapLatch(Fmmu_Core_t core, Fmmu_Type_t fmmuType, uint8_t regionId)
{
    lld_status_t errorId = FMMU_NO_ERROR;
    uint32_t base = Fmmu_Get_Base(core, fmmuType);
    uint32_t remapLatchValue = readl(base + FMMU_REMAP_EN_LATCH(regionId));

    if (Fmmu_Get_Monitor(core, fmmuType))
    {
        remapLatchValue |= FMMU_REMAP_EN_OFF(regionId % FMMU_EN_NUM);
        remapLatchValue &= ~(FMMU_REMAP_MON_EN_OFF(regionId % FMMU_EN_NUM));
    }
    else
    {
        remapLatchValue |= FMMU_REMAP_EN_OFF(regionId % FMMU_EN_NUM);
    }

    writel(remapLatchValue, base + FMMU_REMAP_EN_LATCH(regionId));
    if (remapLatchValue != readl(base + FMMU_REMAP_EN_LATCH(regionId))) {
        errorId = FMMU_E_WRIT_REG_EXCEPTION;
    }/* else not needed */

    return errorId;
}


/***************************************************************************************************
 *                                  Global Function Declarations                                   *
 **************************************************************************************************/
lld_status_t Fmmu_Init(Fmmu_Core_t core, const Fmmu_ConfigType * config, uint32_t regionNum)
{
    lld_status_t errorId = 0;

    if (core >= FMMU_CORE_MAX)
    {
        errorId = FMMU_E_PARAM_INVALID;
    }
    else if(regionNum > (FMMU_REGION_NUM_MAX))
    {
        errorId = FMMU_E_PARAM_INVALID;
    }
    else if(config == NULL_PTR)
    {
        errorId = FMMU_E_PARAM_POINTER;
    }
    else
    {
        errorId = Fmmu_Init_Check_Config(core, config, regionNum);
        if(FMMU_NO_ERROR == errorId){
            for (uint32_t i = 0; i < regionNum; i++)
            {
                errorId = FMMU_Config_RemapParam(core, &(config[i].regionConfig));
                if(FMMU_NO_ERROR != errorId){
                    break;
                }

                errorId = FMMU_Config_RemapEn(core, config[i].regionConfig.type, config[i].regionConfig.regionId, config[i].en);
                if(FMMU_NO_ERROR != errorId){
                    break;
                }
                if (config[i].lock == FMMU_LOCK_EN)
                {
                    errorId = FMMU_Config_RemapLatch(core, config[i].regionConfig.type, config[i].regionConfig.regionId);
                    if(FMMU_NO_ERROR != errorId){
                        break;
                    }
                }
            }
        }
    }

    return errorId;
}

lld_status_t Fmmu_RegionEnable(Fmmu_Core_t core, Fmmu_Type_t remapType, uint32_t regionId, Fmmu_RegionEn_t En)
{
    lld_status_t errorId = 0;

    if (core >= FMMU_CORE_MAX)
    {
        errorId = FMMU_E_PARAM_INVALID;
    }else{
        errorId = Fmmu_Check_RegionId(core, remapType, regionId);
        if(FMMU_NO_ERROR == errorId)
        {
            errorId = FMMU_Config_RemapEn(core, remapType, regionId, En);
        }
    }

    return errorId;
}

lld_status_t Fmmu_RegionLock(Fmmu_Core_t core, Fmmu_Type_t remapType, uint32_t regionId)
{
    lld_status_t errorId = FMMU_NO_ERROR;

    if (core >= FMMU_CORE_MAX)
    {
        errorId = FMMU_E_PARAM_INVALID;
    }
    else
    {
        errorId = Fmmu_Check_RegionId(core, remapType, regionId);

        if(FMMU_NO_ERROR == errorId)
        {
            errorId = FMMU_Config_RemapLatch(core, remapType, regionId);
        }
    }

    return errorId;
}

lld_status_t Fmmu_RegionConfig(Fmmu_Core_t core, const Fmmu_RegionConfigType * config)
{
    lld_status_t errorId = FMMU_NO_ERROR;

    if (core >= FMMU_CORE_MAX)
    {
        errorId = FMMU_E_PARAM_INVALID;
    }
    else if(config == NULL_PTR)
    {
        errorId = FMMU_E_PARAM_POINTER;
    }
    else{
        errorId = Fmmu_Check_RegionId(core, config->type, config->regionId);
        if(FMMU_NO_ERROR == errorId)
        {
            errorId = Fmmu_Check_RemapAddr(config);
            if(FMMU_NO_ERROR == errorId)
            {
                errorId = FMMU_Config_RemapParam(core, config);
            }
        }
    }

    return errorId;
}

Fmmu_RegionEn_t Fmmu_GetRegionEnStatus(Fmmu_Core_t core, Fmmu_Type_t remapType, uint32_t regionId)
{
    uint32_t retVal = FMMU_REGION_DIS;
    uint32_t base = Fmmu_Get_Base(core, remapType);

    if (core >= FMMU_CORE_MAX || 0 == base)
    {
        retVal = FMMU_REGION_EN_ERROR;
    }else{
        retVal = Fmmu_Check_RegionId(core, remapType, regionId);
        if(FMMU_REGION_DIS == retVal)
        {
            retVal = Fmmu_Get_RemapEnStatus(base, regionId);
        }
        else
        {
            retVal = FMMU_REGION_EN_ERROR;
        }
    }

    return (Fmmu_RegionEn_t)retVal;
}

Fmmu_RegionLatch_t Fmmu_GetRegionLockStatus(Fmmu_Core_t core, Fmmu_Type_t remapType, uint32_t regionId)
{
    uint32_t retVal = FMMU_LOCK_DIS;
    uint32_t base = Fmmu_Get_Base(core, remapType);

    if (core >= FMMU_CORE_MAX || 0 == base)
    {
        retVal = FMMU_LOCK_ERROR;
    }else{
        retVal = Fmmu_Check_RegionId(core, remapType, regionId);
        if(FMMU_LOCK_DIS == retVal){
            retVal =  Fmmu_Get_RemapLatchStatus(base, regionId);
        }
        else
        {
            retVal = FMMU_LOCK_ERROR;
        }
    }

    return (Fmmu_RegionLatch_t)retVal;
}

lld_status_t Fmmu_GetRegionConfig(Fmmu_Core_t core, Fmmu_Type_t remapType, uint32_t regionId, Fmmu_RegionConfigType * config)
{
    lld_status_t errorId = FMMU_NO_ERROR;
    uint32_t base = Fmmu_Get_Base(core, remapType);

    if (core >= FMMU_CORE_MAX || 0 == base)
    {
        errorId = FMMU_E_PARAM_INVALID;
    }else{
        errorId = Fmmu_Check_RegionId(core, remapType, regionId);
        if(FMMU_NO_ERROR == errorId){
            config->regionId = regionId;
            config->type = remapType;
            config->remapSize = (Fmmu_RemapSize_t)(readl(base + FMMU_REMAP_CTL(regionId)) & FMMU_REMAP_SIZE_MASK);
            config->srcAddr = FMMU_OFF_TO_ADDR(readl(base + FMMU_REMAP_SRC_ADDR(regionId)) & FMMU_REMAP_SRC_ADDR_MASK);
            config->dstAddr = FMMU_OFF_TO_ADDR(readl(base + FMMU_REMAP_DST_ADDR(regionId)) & FMMU_REMAP_DST_ADDR_MASK);
        }
    }

    return errorId;
}

// if return 0xFFFFFFFF, is error.
uint32_t Fmmu_GetRemapDstAddr(Fmmu_Core_t core, uint32_t srcAddr, uint32_t size)
{
    uint32_t retVal;
    uint32_t remapSize;
    uint64_t remapSrcAddr;
    uint32_t remapDstAddr = 0;
    uint8_t i, j;

    if (core >= FMMU_CORE_MAX)
    {
        retVal = 0xFFFFFFFF;
    }
    else
    {
        for (i = 0; i < FMMU_MAX_NUM; i++)
        {
            if (Fmmu_AttributeTable[i].core == core)
            {
                Fmmu_Type_t type = Fmmu_AttributeTable[i].fmmuType;
                uint32_t base = Fmmu_Get_Base(core, type);

                for (j = 0; j < Fmmu_AttributeTable[i].regionNum; j++)
                {
                    if (Fmmu_Get_RemapEnStatus(base, j))
                    {
                        remapSrcAddr = FMMU_OFF_TO_ADDR(readl(base + FMMU_REMAP_SRC_ADDR(j)) & FMMU_REMAP_SRC_ADDR_MASK);
                        remapSize = FMMU_REMAP_SIZE(readl(base + FMMU_REMAP_CTL(j)) & FMMU_REMAP_SIZE_MASK);

                        if (srcAddr >= remapSrcAddr && srcAddr <= (remapSrcAddr + remapSize) &&
                            ((uint64_t)srcAddr + size) <= (remapSrcAddr + remapSize))
                        {
                            remapDstAddr = FMMU_OFF_TO_ADDR(readl(base + FMMU_REMAP_DST_ADDR(j)) & FMMU_REMAP_DST_ADDR_MASK);
                            break;
                        } /* else not needed */
                    } /* else not needed */
                }
                if (remapDstAddr !=0)
                {
                    break;
                }
            }/* else not needed */
        }

        if (remapDstAddr != 0)
        {
            retVal = remapDstAddr + (srcAddr - remapSrcAddr);
        }
        else
        {
            retVal = 0xFFFFFFFF;
        }
    }

    return retVal;
}
#ifdef CFG_PLATFORM_MCAL
#define FMMU_STOP_SEC_CODE
#include "Fmmu_MemMap.h"
#endif /* #ifdef CFG_PLATFORM_MCAL */
/* End of file */
